#include "List.h"
#include <iostream>
#include <sstream>
#include <cassert>
#include <typeinfo>	// Added on 16/4
#include <stdio.h>	// Added on 16/4
using namespace std;
using namespace cs236703_spring2012_hw2;

// NOTE: this is the only place where code is added to this namespace!
namespace cs236703_spring2012_hw2
{
// Nodes counter, used by the Node class.
int nodesCount = 0;
}

//---------------------------------------------------------------------
//						Testing helper functions
//---------------------------------------------------------------------

// Use this class to auto-delete pointers even in case of an exception
// There are much better smart pointer classes in C++, but this provides
// the minimal needs.
template<class T>
struct AutoDeleter
{
	T* ptr;
	AutoDeleter(T* p) :
		ptr(p)
	{
	}
	~AutoDeleter()
	{
		delete ptr;
	}
};

// This is the prototype of the test method (as simple as they get)
typedef void (*test)(void);

// The test runner
void RunTest(test func, const char* name, const type_info* exceptionType)
{
	stringstream error;
	cout << "Testing " << name << ": " << endl;
	try
	{
		func();
		if (exceptionType != NULL)
			error << "Failed. Expected exception of type "
					<< exceptionType->name() << ", but none was thrown!";
	} catch (exception& ex)
	{
		if (exceptionType != NULL)
		{
			if (typeid(ex) != *exceptionType)
						error << "Failed. Expected exception of type "
								<< exceptionType->name() << ", but a "
								<< typeid(ex).name() << " was thrown!";
				}
				else
					error << "Failed. An unexpected exception of type "
							<< typeid(ex).name() << " was thrown!";
			} catch (...)
			{
				error
						<< "Failed. An unidentified error was thrown (probably memory corruption or so)!";
			}
			if (error.str().length() > 0)
				cout << error.str() << endl << endl;
			else
				cout << "Passed." << endl << endl;
		}

		// Run a non-throwing test function.
#define RUN_TEST(func) \
	RunTest(func, #func, NULL)
		// Run a test function that is expected to throw.
		// Pass the exception class as the second argument.
#define RUN_THROWING_TEST(func, ex) \
	RunTest(func, #func, &typeid(ex))

		// Unit Test like asserts. Use macros instead of functions
		// to keep the additional info given by assert (the asserted
		// expression, for instance)
#define AssertTrue(value)	\
	assert(value)
#define AssertFalse(value)	\
	assert(!(value))
#define AssertEquals(val1, val2)	\
	assert((val1) == (val2))

		//---------------------------------------------------------------------
		//							Test functions
		//---------------------------------------------------------------------

		void TestBasics()
		{
			List* l = GetNewList();
			AutoDeleter<List> ad1(l);
			l->AddToFront(1, true);
			l->AddToFront(2, true);
			l->AddToFront(3, true);
			Iterator* i = l->GetIterator();
			AutoDeleter<Iterator> ad2(i);
			stringstream out;
			out << i->Next();
			out << i->Next();
			out << i->Next();
			AssertEquals(out.str(), string("321"));
		}

		void TestIteration()
		{
			List* l = GetNewList();
			AutoDeleter<List> ad1(l);
			l->AddToBack(1, true);
			l->AddToBack(2, true);
			l->AddToBack(3, true);
			l->AddToBack(4, true);
			l->AddToBack(5, true);
			Iterator* i = l->GetIterator();
			AutoDeleter<Iterator> ad2(i);
			stringstream out;
			i->Next();
			i->Next();
			i->Next(); // now at 3
			out << i->Previous(); // return 2, now at 2
			out << i->Next(); // return 3, now at 3
			i->Next();
			i->Next(); // now at 5
			out << i->Previous(); // return 4, now at 4
			AssertEquals(out.str(), string("234"));
		}

		void TestRemove()
		{
			List* l = GetNewList();
			AutoDeleter<List> ad1(l);
			l->AddToBack(1, true);
			l->AddToBack(2, true);
			l->AddToBack(3, true);
			l->AddToBack(4, true);
			Iterator* i = l->GetIterator();
			AutoDeleter<Iterator> ad2(i);
			stringstream out;
			i->Next();
			i->Next();
			i->Remove();
			AssertTrue(i->HasNext()); // node extracted from list, but removing iterator can still move on
			i = l->GetIterator();
			AutoDeleter<Iterator> ad3(i);
			i->Next();
			AssertEquals(i->Next(), 3); // second element is now 3
		}

		void TestImmutableChangeException()
		{
			List* l = GetNewList();
			AutoDeleter<List> ad1(l);
			l->AddToFront(1, false);
			l->AddToBack(2, true);
			Iterator* i = l->GetIterator();
			AutoDeleter<Iterator> ad2(i);
			i->Next();
			i->Set(10); // should work
			i->Next();
			i->Set(20); // should throw ImmutableChangeException
			AssertTrue(false);
		}

		void TestIllegalStateException()
		{
			List* l = GetNewList();
			AutoDeleter<List> ad1(l);
			Iterator* i = l->GetIterator();
			AutoDeleter<Iterator> ad2(i);
			i->AddBefore(1, true); // should throw IllegalStateException
			AssertTrue(false);
		}

		void TestNoSuchElementException()
		{
			List* l = GetNewList();
			AutoDeleter<List> ad1(l);
			Iterator* i = l->GetIterator();
			AutoDeleter<Iterator> ad2(i);
			i->Next(); // should throw NoSuchElementException
			AssertTrue(false);
		}

		void TestListModifiedException()
		{
			List* l = GetNewList();
			AutoDeleter<List> ad1(l);
			l->AddToFront(1, false);
			l->AddToFront(2, false);
			Iterator* i = l->GetIterator(); // will remove an item
			Iterator* j = l->GetIterator(); // will try to move after removal
			AutoDeleter<Iterator> ad2(i);
			AutoDeleter<Iterator> ad3(j);
			i->Next();
			i->Remove();
			j->Next(); // should throw ListModifiedException
			AssertTrue(false);
		}

		void TestRefCounts()
		{
			List* l = GetNewList();
			int initCount = nodesCount;
			AutoDeleter<List> ad1(l);
			l->AddToFront(1, false);
			l->AddToFront(2, false);
			AssertEquals(nodesCount, initCount + 2);
			Iterator* i;
			{
				i = l->GetIterator();
				AutoDeleter<Iterator> ad2(i);
				i->Next();
				i->Remove();
				AssertEquals(nodesCount, initCount + 2); // node still pointed by i
			}
			AssertEquals(nodesCount, initCount + 1); // after i was deleted, node was deleted too
			{
				i = l->GetIterator();
				AutoDeleter<Iterator> ad3(i);
				i->Next();
				i->Remove();
			}
			AssertEquals(nodesCount, initCount);
		}

		// Feel free to adapt the Java tests you got to C++...

		//---------------------------------------------------------------------
		//						Where it all starts
		//---------------------------------------------------------------------

		int firstInList(List* list)
		{
			Iterator* i = list->GetIterator();
			int res = i->Next();
			delete i;
			return res;
		}

		int lastInList(List* list)
		{
			Iterator* i = list->GetIterator();
			while (i->HasNext())
			{
				i->Next();
			}
			int res = i->Get();
			delete i;
			return res;
		}

		// true if List is empty
		bool isEmpty(List* list)
		{
			Iterator* i = list->GetIterator();
			bool res = (!i->HasNext());
			delete i;
			return res;
		}
		void testList()
		{
			List* ls = GetNewList();
			Iterator* i = ls->GetIterator();
			AssertTrue(isEmpty(ls));
			try
			{
				i->Next();
				AssertTrue(false);
			} catch (NoSuchElementException& e)
			{
				AssertTrue(true);
			}
			delete i;
			i = ls->GetIterator();
			AssertTrue(isEmpty(ls));
			try
			{
				i->Previous();
				AssertTrue(false);
			} catch (NoSuchElementException& e)
			{
				AssertTrue(true);
			}
			delete i;
			//	try {
			//	    lastInList(ls);
			//	    AssertTrue(false);
			//	} catch (NoSuchElementException& e) {
			//	    AssertTrue(true);
			//	}

			ls->AddToBack(5);
			AssertEquals(int(5), firstInList(ls));
			AssertEquals(int(5), lastInList(ls));
			ls->AddToBack(7);
			AssertEquals(int(5), firstInList(ls));
			AssertEquals(int(7), lastInList(ls));
			ls->AddToBack(8, true);
			AssertEquals(int(5), firstInList(ls));
			AssertEquals(int(8), lastInList(ls));
			ls->AddToBack(3, false);
			AssertEquals(int(5), firstInList(ls));
			AssertEquals(int(3), lastInList(ls));

			ls->AddToFront(0);
			AssertEquals(int(0), firstInList(ls));
			AssertEquals(int(3), lastInList(ls));
			ls->AddToFront(-5, false);
			AssertEquals(int(-5), firstInList(ls));
			AssertEquals(int(3), lastInList(ls));
			ls->AddToBack(8008, false);
			AssertEquals(int(-5), firstInList(ls));
			AssertEquals(int(8008), lastInList(ls));
			ls->AddToFront(666, true);
			AssertEquals(int(666), firstInList(ls));
			AssertEquals(int(8008), lastInList(ls));
			delete ls;
		}

		void testIterator()
		{
			List* list = GetNewList();
			Iterator* i = list->GetIterator();
			AssertFalse(i->HasNext());
			try
			{
				i->Next();
				AssertTrue(false);
			} catch (NoSuchElementException& e)
			{
				AssertTrue(true);
			}
			list->AddToFront(3);
			AssertFalse(i->HasNext());
			try
			{
				i->Next();
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			try
			{
				i->Remove();
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			delete i;
			i = list->GetIterator();
			AssertTrue(i->HasNext());
			AssertEquals(int(3), i->Next());
			AssertFalse(i->HasNext());
			try
			{
				i->Next();
				AssertTrue(false);
			} catch (NoSuchElementException& e)
			{
				AssertTrue(true);
			}
			delete i;
			i = list->GetIterator();
			try
			{
				i->Remove();
				AssertTrue(false);
			} catch (IllegalStateException& e)
			{
				AssertTrue(true);
			}

			i->Next();
			i->Remove();

			AssertTrue(isEmpty(list));
			try
			{
				i->Next();
				AssertTrue(false);
			} catch (NoSuchElementException& e)
			{
				AssertTrue(true);
			}
			try
			{
				i->Remove();
				AssertTrue(false);
			} catch (IllegalStateException& e)
			{
				AssertTrue(true);
			}
			list->AddToBack(1);
			list->AddToBack(2);
			Iterator* j = list->GetIterator();
			try
			{
				i->Remove();
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			AssertEquals(int(1), j->Next());
			j->Remove();

			try
			{
				j->Remove();
				AssertTrue(false);
			} catch (IllegalStateException& e)
			{
				AssertTrue(true);
			}
			AssertEquals(int(2), j->Next());
			j->Remove();
			AssertTrue(isEmpty(list));
			delete i;
			delete j;
			delete list;
		}

		//    void testDescIterator() {
		//    List* list = GetNewList();
		//	Iterator* i = list.descendingIterator();
		//	AssertFalse(i->HasNext());
		//	try {
		//	    i->Next();
		//	    AssertTrue(false);
		//	} catch (NoSuchElementException& e) {
		//	    AssertTrue(true);
		//	}
		//
		//	list->AddToFront(3);
		//	AssertFalse(i->HasNext());
		//	try {
		//	    i->Next();
		//	    AssertTrue(false);
		//	} catch (ConcurrentModificationException& e) {
		//	    AssertTrue(true);
		//	}
		//	try {
		//	    i->Remove();
		//	    AssertTrue(false);
		//	} catch (ConcurrentModificationException& e) {
		//	    AssertTrue(true);
		//	}
		//
		//	i = list.descendingIterator();
		//	AssertTrue(i->HasNext());
		//	AssertEquals(int(3), i->Next());
		//	AssertFalse(i->HasNext());
		//	try {
		//	    i->Next();
		//	    AssertTrue(false);
		//	} catch (NoSuchElementException& e) {
		//	    AssertTrue(true);
		//	}
		//
		//	i = list.descendingIterator();
		//	try {
		//	    i->Remove();
		//	    AssertTrue(false);
		//	} catch (IllegalStateException& e) {
		//	    AssertTrue(true);
		//	}
		//	i->Next();
		//	i->Remove();
		////	AssertTrue(list.isEmpty());
		//	try {
		//	    i->Next();
		//	    AssertTrue(false);
		//	} catch (NoSuchElementException& e) {
		//	    AssertTrue(true);
		//	}
		//	try {
		//	    i->Remove();
		//	    AssertTrue(false);
		//	} catch (IllegalStateException& e) {
		//	    AssertTrue(true);
		//	}
		//
		//	list->AddToBack(1);
		//	list->AddToBack(2);
		//	Iterator* j = list.descendingIterator();
		//	try {
		//	    i->Remove();
		//	    AssertTrue(false);
		//	} catch (ConcurrentModificationException& e) {
		//	    AssertTrue(true);
		//	}
		//	AssertEquals(int(2), j->Next());
		//	j->Remove();
		//	try {
		//	    j->Remove();
		//	    AssertTrue(false);
		//	} catch (IllegalStateException& e) {
		//	    AssertTrue(true);
		//	}
		//	AssertEquals(int(1), j->Next());
		//	j->Remove();
		////	AssertTrue(list.isEmpty());
		//
		//    }

		void testIteratorPrev()
		{
			List* list = GetNewList();
			Iterator* i = list->GetIterator();

			AssertFalse(i->HasNext());
			list->AddToFront(1);
			AssertFalse(i->HasNext());
			try
			{
				i->Next();
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			delete i;
			i = list->GetIterator();
			AssertTrue(i->HasNext());
			AssertEquals(int(1), i->Next());
			list->AddToBack(2);
			try
			{
				i->Next();
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			list->AddToBack(3);
			list->AddToBack(4);
			delete i;
			i = list->GetIterator();
			AssertTrue(i->HasNext());
			AssertEquals(int(1), i->Next());
			AssertTrue(i->HasNext());
			AssertEquals(int(2), i->Next());
			AssertTrue(i->HasNext());
			AssertEquals(int(3), i->Next());
			AssertTrue(i->HasNext());
			AssertEquals(int(4), i->Next());
			AssertFalse(i->HasNext());
			try
			{
				i->Next();
				AssertTrue(false);
			} catch (NoSuchElementException& e)
			{
				AssertTrue(true);
			}
			list->AddToBack(5);
			Iterator* j = list->GetIterator();
			try
			{
				i->Next();
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			AssertEquals(int(1), j->Next());
			delete i;
			delete j;
			delete list;
		}

		void testIteratorNext()
		{
			List* list = GetNewList();
			Iterator* i = list->GetIterator();
			AssertFalse(i->HasPrevious());
			list->AddToFront(1);
			AssertFalse(i->HasPrevious());
			try
			{
				i->Previous();
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			delete i;
			i = list->GetIterator();
			AssertFalse(i->HasPrevious());
			list->AddToBack(2);
			try
			{
				i->Next();
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			list->AddToBack(3);
			list->AddToBack(4);
			delete i;
			i = list->GetIterator();
			AssertEquals(int(1), i->Next());
			AssertEquals(int(2), i->Next());
			AssertEquals(int(3), i->Next());
			AssertEquals(int(4), i->Next());
			AssertTrue(i->HasPrevious());
			AssertEquals(int(3), i->Previous());
			AssertTrue(i->HasPrevious());
			AssertEquals(int(2), i->Previous());
			AssertTrue(i->HasPrevious());
			AssertEquals(int(1), i->Previous());
			AssertFalse(i->HasPrevious());
			try
			{
				i->Previous();
				AssertTrue(false);
			} catch (NoSuchElementException& e)
			{
				AssertTrue(true);
			}
			delete i;
			i = list->GetIterator();
			i->Next();
			list->AddToBack(5);
			Iterator* j = list->GetIterator();
			try
			{
				i->Previous();
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			AssertEquals(int(1), j->Next());
			try
			{
				j->Previous();
				AssertTrue(false);
			} catch (NoSuchElementException& e)
			{
				AssertTrue(true);
			}
			AssertEquals(int(2), j->Next());
			AssertEquals(int(1), j->Previous());
			delete i;
			delete j;
			delete list;
		}

		void testIteratorRemove()
		{
			List* list = GetNewList();
			Iterator* i = list->GetIterator();

			try
			{
				i->Remove();
				AssertTrue(false);
			} catch (IllegalStateException& e)
			{
				AssertTrue(true);
			}

			list->AddToBack(1);
			list->AddToBack(2);
			list->AddToBack(3);
			list->AddToBack(4);
			delete i;
			i = list->GetIterator();
			try
			{
				i->Remove();
				AssertTrue(false);
			} catch (IllegalStateException& e)
			{
				AssertTrue(true);
			}
			i->Next();
			i->Remove();
			try
			{
				i->Remove();
				AssertTrue(false);
			} catch (IllegalStateException& e)
			{
				AssertTrue(true);
			}
			delete i;
			i = list->GetIterator();
			AssertEquals(int(2), i->Next());
			AssertFalse(i->HasPrevious());
			AssertTrue(i->HasNext());
			i->Remove();
			i->Next();
			i->Remove();
			i->Next();
			i->Remove();
			try
			{
				i->Next();
				AssertTrue(false);
			} catch (NoSuchElementException& e)
			{
				AssertTrue(true);
			}
			AssertTrue(isEmpty(list));

			list->AddToFront(4);
			list->AddToFront(3);
			list->AddToFront(2);
			delete i;
			i = list->GetIterator();
			i->Next();
			list->AddToFront(1);
			Iterator* j = list->GetIterator();
			try
			{
				i->Remove();
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			AssertEquals(int(1), j->Next());
			delete i;
			i = list->GetIterator();
			i->Next();
			delete j;
			j = list->GetIterator();
			j->Next();
			j->Remove();
			try
			{
				i->Next();
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			try
			{
				i->Remove();
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			delete i;
			delete j;
			delete list;
		}

		void testIteratorSet()
		{
			List* list = GetNewList();
			Iterator* i = list->GetIterator();

			try
			{
				i->Set(5);
				AssertTrue(false);
			} catch (IllegalStateException& e)
			{
				AssertTrue(true);
			}

			list->AddToBack(1, false);
			list->AddToBack(2, false);
			list->AddToBack(3, false);
			list->AddToBack(4, false);
			delete i;
			i = list->GetIterator();
			try
			{
				i->Set(5);
				AssertTrue(false);
			} catch (IllegalStateException& e)
			{
				AssertTrue(true);
			}
			i->Next();
			i->Set(0);
			i->Set(4);
			i->Next();
			i->Set(3);
			i->Next();
			i->Set(2);
			i->Next();
			i->Set(1);
			Iterator* j = list->GetIterator();
			AssertEquals(int(4), j->Next());
			AssertEquals(int(3), j->Next());
			AssertEquals(int(2), j->Next());
			AssertEquals(int(1), j->Next());
			delete i;
			i = list->GetIterator();
			i->Next();
			list->AddToFront(5, false);
			delete j;
			j = list->GetIterator();
			j->Next();
			try
			{
				i->Set(0);
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			j->Set(0);
			AssertEquals(int(4), j->Next());
			AssertEquals(int(0), j->Previous());
			delete list;
			list = GetNewList();
			list->AddToFront(0);
			list->AddToFront(-2, true);
			list->AddToFront(-4, false);
			list->AddToBack(2);
			list->AddToBack(4, false);
			list->AddToBack(6, true);
			delete i;
			i = list->GetIterator();
			i->Next();
			i->Set(-3);
			i->Set(-5);
			i->Next();
			try
			{
				i->Set(666);
				AssertTrue(false);
			} catch (ImmutableModificationException& e)
			{
				AssertTrue(true);
			}
			i->Next();
			try
			{
				i->Set(8008);
				AssertTrue(false);
			} catch (ImmutableModificationException& e)
			{
				AssertTrue(true);
			}
			i->Next();
			try
			{
				i->Set(541);
				AssertTrue(false);
			} catch (ImmutableModificationException& e)
			{
				AssertTrue(true);
			}
			i->Next();
			i->Set(3);
			i->Next();
			try
			{
				i->Set(1334);
				AssertTrue(false);
			} catch (ImmutableModificationException& e)
			{
				AssertTrue(true);
			}
			delete i;
			i = list->GetIterator();
			AssertEquals(int(-5), i->Next());
			AssertEquals(int(-2), i->Next());
			AssertEquals(int(0), i->Next());
			AssertEquals(int(2), i->Next());
			AssertEquals(int(3), i->Next());
			AssertEquals(int(6), i->Next());
			delete i;
			i = list->GetIterator();
			AssertEquals(int(-5), i->Next());
			delete j;
			j = list->GetIterator();
			j->Next();
			j->Set(-8);
			AssertEquals(int(-2), i->Next()); // no
			// ConcurrentModificationException
			AssertEquals(int(-8), i->Previous()); // also i is updated too
			delete i;
			delete j;
			delete list;
		}

		void testIteratorAddBefore()
		{
			List* list = GetNewList();
			list->AddToBack(2);
			list->AddToBack(1);
			Iterator* i = list->GetIterator();
			cout<<"HEP HEP1"<<endl;
			try
			{
				i->AddBefore(666, true);
				AssertTrue(false);
			} catch (IllegalStateException& e)
			{
				AssertTrue(true);
			}
			cout<<"HEP HEP2"<<endl;
			i->Next();
			i->AddBefore(0, false);
			try
			{
				i->Set(1334);
				AssertTrue(false);
			} catch (IllegalStateException& e) //TODO SAME
			{
				AssertTrue(true);
			}
			cout<<"HEP HEP3"<<endl;
			AssertEquals(int (0), i->Previous());
			i->Set(-1);
			i->AddBefore(-2, true);
			//TODO WHY?????
			try
			{
				i->AddBefore(8008, true);
				AssertTrue(false);
			} catch (IllegalStateException& e)
			{
				AssertTrue(true);
			}
			cout<<"HEP HEP4"<<endl;
			AssertEquals(int (-2), i->Previous());
			try
			{
				i->Set(8008);
				AssertTrue(false);
			} catch (ImmutableModificationException& e)
			{
				AssertTrue(true);
			}
			cout<<"HEP HEP5"<<endl;
			list->AddToBack(-9);
			try
			{
				i->AddBefore(8008, true);
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			cout<<"HEP HEP6"<<endl;
			delete i;
			i = list->GetIterator();
			Iterator* j = list->GetIterator();
			i->Next();
			i->AddBefore(-27, true);
			try
			{
				j->AddBefore(8008, true);
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			cout<<"HEP HEP7"<<endl;
			delete i;
			delete j;
			delete list;
		}

		void testIteratorAddAfter()
		{
			List* list = GetNewList();
			list->AddToBack(2);
			list->AddToBack(0);
			Iterator* i = list->GetIterator();
			cout<<"HEP HEP1"<<endl;
			try
			{
				i->AddAfter(666, true);
				AssertTrue(false);
			} catch (IllegalStateException& e)
			{
				AssertTrue(true);
			}
			cout<<"HEP HEP2"<<endl;
			i->Next();
			i->AddAfter(3, false);
			try
			{
				i->Set(1334);
				AssertTrue(false);
			} catch (IllegalStateException& e) //WHAT SHOULD WE DO?IllegalStateException
			{
				AssertTrue(true);
			}
			cout<<"HEP HEP3"<<endl;
			AssertEquals(int (3), i->Next());
			i->Set(4);
			i->AddAfter(5, true);
			//TODO WHY IS THAT??????
			try
			{
				i->AddAfter(8008, true);
				AssertTrue(false);
			} catch (IllegalStateException& e)
			{
				AssertTrue(true);
			}
			cout<<"HEP HEP4"<<endl;
			AssertEquals(int (5), i->Next());
			try
			{
				i->Set(8008);
				AssertTrue(false);
			} catch (ImmutableModificationException& e)
			{
				AssertTrue(true);
			}
			cout<<"HEP HEP5"<<endl;
			list->AddToFront(9);
			try
			{
				i->AddAfter(8008, true);
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			cout<<"HEP HEP6"<<endl;
			delete i;
			i = list->GetIterator();
			Iterator* j = list->GetIterator();
			i->Next();
			i->AddAfter(1, true);
			cout<<"HEP HEP7"<<endl;
			try
			{
				j->AddAfter(8008, true);
				AssertTrue(false);
			} catch (ConcurrentModificationException& e)
			{
				AssertTrue(true);
			}
			delete i;
			delete j;
			delete list;
		}

		int main()
		{
			RUN_TEST(TestBasics);
			RUN_TEST(TestIteration);
			RUN_TEST(TestRemove);
			RUN_TEST(TestRefCounts);
			RUN_THROWING_TEST(TestImmutableChangeException, ImmutableModificationException);
			RUN_THROWING_TEST(TestIllegalStateException, IllegalStateException);
			RUN_THROWING_TEST(TestNoSuchElementException, NoSuchElementException);
			RUN_THROWING_TEST(TestListModifiedException, ConcurrentModificationException);
			RUN_TEST(testList);
			RUN_TEST(testIterator);
			RUN_TEST(testIteratorPrev);
			RUN_TEST(testIteratorNext);
			RUN_TEST(testIteratorRemove);
			RUN_TEST(testIteratorSet);
			RUN_TEST(testIteratorAddBefore);
			RUN_TEST(testIteratorAddAfter);
			cout << "All done";
			//getchar();
			return 0;
		}
